<template>
  <div :class="[prefixCls, `${prefixCls}--${theme}`]">
    <a-breadcrumb :routes="routes">
      <template #itemRender="{ route, routes: routesMatched, paths }">
        <Icon :icon="getIcon(route)" v-if="getShowBreadCrumbIcon && getIcon(route)"/>
        <span v-if="!hasRedirect(routesMatched, route)">
          {{ t(route.name || route.meta.title) }}
        </span>
        <router-link v-else to="" @click="handleClick(route, paths, $event)">
          {{ t(route.name || route.meta.title) }}
        </router-link>
      </template>
    </a-breadcrumb>
  </div>
</template>
<script lang="ts">
import type {RouteLocationMatched} from 'vue-router';
import {useRouter} from 'vue-router';
import type {Menu} from '/@/router/types';

import {defineComponent, ref, watchEffect} from 'vue';

import {Breadcrumb} from 'ant-design-vue';
import Icon from '@/components/Icon/Icon.vue';

import {useDesign} from '/@/hooks/web/useDesign';
import {useRootSetting} from '/@/hooks/setting/useRootSetting';
import {useGo} from '/@/hooks/web/usePage';
import {useI18n} from '/@/hooks/web/useI18n';

import {propTypes} from '/@/utils/propTypes';
import {isString} from '/@/utils/is';
import {filter} from '/@/utils/helper/treeHelper';
import {getMenus} from '/@/router/menus';

import {REDIRECT_NAME} from '/@/router/constant';
import {getAllParentPath} from '/@/router/helper/menuHelper';

export default defineComponent({
  name: 'LayoutBreadcrumb',
  components: {Icon, [Breadcrumb.name]: Breadcrumb},
  props: {
    theme: propTypes.oneOf(['dark', 'light']),
  },
  setup() {
    const routes = ref<RouteLocationMatched[]>([]);
    const {currentRoute} = useRouter();
    const {prefixCls} = useDesign('layout-breadcrumb');
    const {getShowBreadCrumbIcon} = useRootSetting();
    const go = useGo();

    const {t} = useI18n();
    watchEffect(async () => {
      if (currentRoute.value.name === REDIRECT_NAME) return;
      const menus = await getMenus();
      const routeMatched = currentRoute.value.matched;
      const cur = routeMatched?.[routeMatched.length - 1];
      let path = currentRoute.value.path;

      if (cur && cur?.meta?.currentActiveMenu) {
        path = cur.meta.currentActiveMenu as string;
      }
      const parent = getAllParentPath(menus, path);
      const filterMenus = menus.filter((item) => item.path === parent[0]);
      const matched = getMatched(filterMenus, parent) as any;
      if (!matched || matched.length === 0) return;
      const breadcrumbList = filterItem(matched);
      if (currentRoute.value.meta?.currentActiveMenu) {
        breadcrumbList.push({
          ...currentRoute.value,
          name: currentRoute.value.meta?.title || currentRoute.value.name,
        } as unknown as RouteLocationMatched);
      }
      routes.value = breadcrumbList;
    });

    function getMatched(menus: Menu[], parent: string[]) {
      const metched: Menu[] = [];
      menus.forEach((item) => {
        if (parent.includes(item.path)) {
          metched.push({
            ...item,
            name: item.meta?.title || item.name,
          });
        }
        if (item.children?.length) {
          metched.push(...getMatched(item.children, parent));
        }
      });
      return metched;
    }

    function filterItem(list: RouteLocationMatched[]) {
      return filter(list, (item) => {
        const {meta, name} = item;
        if (!meta) {
          return !!name;
        }
        const {title, hideBreadcrumb, hideMenu} = meta;
        if (!title || hideBreadcrumb || hideMenu) {
          return false;
        }
        return true;
      }).filter((item) => !item.meta?.hideBreadcrumb);
    }

    function handleClick(route: RouteLocationMatched, paths: string[], e: Event) {
      e?.preventDefault();
      const {children, redirect, meta} = route;

      if (children?.length && !redirect) {
        e?.stopPropagation();
        return;
      }
      if (meta?.carryParam) {
        return;
      }

      if (redirect && isString(redirect)) {
        go(redirect);
      } else {
        let goPath = '';
        if (paths.length === 1) {
          goPath = paths[0];
        } else {
          const ps = paths.slice(1);
          const lastPath = ps.pop() || '';
          goPath = `${lastPath}`;
        }
        goPath = /^\//.test(goPath) ? goPath : `/${goPath}`;
        go(goPath);
      }
    }

    function hasRedirect(routes: RouteLocationMatched[], route: RouteLocationMatched) {
      return routes.indexOf(route) !== routes.length - 1;
    }

    function getIcon(route) {
      return route.icon || route.meta?.icon;
    }

    return {routes, t, prefixCls, getIcon, getShowBreadCrumbIcon, handleClick, hasRedirect};
  },
});
</script>
<style lang="less">
@prefix-cls: ~'@{namespace}-layout-breadcrumb';

.@{prefix-cls} {
  display: flex;
  align-items: center;
  padding: 0 8px;

  .ant-breadcrumb-link {
    .anticon {
      margin-right: 4px;
      margin-bottom: 2px;
    }
  }

  &--light {
    .ant-breadcrumb-link {
      color: @breadcrumb-item-normal-color;

      a {
        color: rgb(0 0 0 / 65%);

        &:hover {
          color: @primary-color;
        }
      }
    }

    .ant-breadcrumb-separator {
      color: @breadcrumb-item-normal-color;
    }
  }

  &--dark {
    .ant-breadcrumb-link {
      color: rgb(255 255 255 / 60%);

      a {
        color: rgb(255 255 255 / 80%);

        &:hover {
          color: @white;
        }
      }
    }

    .ant-breadcrumb-separator,
    .anticon {
      color: rgb(255 255 255 / 80%);
    }
  }
}
</style>
